package com.mibotiquin.map;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONObject;

import com.google.android.maps.GeoPoint;

/**This class is responsible for making the request to the server
 * 
 * @author Hector Romero Navarrete
 *
 */
public class PharmacyData {
	
	private String server;
	private GeoPoint myGeoPoint;
	private double distance;//in km
	
	private static double Radius = 6371;//km
	private static final int maxPharmacies = 20;
	
	public PharmacyData(String server,GeoPoint myGeoPoint,String distance){
		this.server = server;
		this.myGeoPoint = myGeoPoint;
		this.distance = Double.parseDouble(distance);
	}
	
	/**process information received from the server
	 * 
	 * @return List<Pharmacies>
	 */
	public List<Pharmacies> run(){
		List<Pharmacies> lpharmacies = null;
		String dateServer = readServerInformation();
		if(dateServer != null){
			try{
				JSONObject jsonObject = new JSONObject(dateServer);
				int jsonStatus = Integer.parseInt(jsonObject.getString("success"));
				if (jsonStatus == 1){
					lpharmacies = new ArrayList<Pharmacies>();
					JSONArray jsonArray = jsonObject.getJSONArray("farmacias");
					int maxSize = Math.min(20,jsonArray.length());
					int j = 0;
					for(int i=0;i<maxSize && j<maxPharmacies;i++){
						String p = jsonArray.getJSONObject(i).getString("poblacion");
						String a = jsonArray.getJSONObject(i).getString("direccion");
						String cp = jsonArray.getJSONObject(i).getString("cp");
						double lon = Double.parseDouble(jsonArray.getJSONObject(i).getString("longitud"));
						double lat = Double.parseDouble(jsonArray.getJSONObject(i).getString("latitud"));
						int g = jsonArray.getJSONObject(i).getInt("guardia");
						GeoPoint aux = new GeoPoint((int)(lat*1E6),(int)(lon*1E6));
						if (distance(myGeoPoint,aux) <= distance){
							lpharmacies.add(new Pharmacies(p,a,cp,lon,lat,g));
							j++;
						}
					}
				}
			}catch (Exception e){	
				e.printStackTrace();
			}
		}
		return lpharmacies;
	}
	
	/**make the request
	 * 
	 * @return String
	 */
	private String readServerInformation(){
		StringBuilder builder = new StringBuilder();
		HttpClient client = new DefaultHttpClient();
		HttpGet httpGet = new HttpGet(server);
		try{
			HttpResponse reply = client.execute(httpGet);
			StatusLine statusLine = reply.getStatusLine();
			int statusCode = statusLine.getStatusCode();
			if(statusCode == 200){
				HttpEntity entity = reply.getEntity();
				InputStream contenido = entity.getContent();
				BufferedReader reader = new BufferedReader(new InputStreamReader(contenido));
				String line;
				while ((line=reader.readLine()) != null){
					builder.append(line);
				}
			}else{	
			}
		}catch (ClientProtocolException e){
			e.printStackTrace();
		}catch (IOException e){
			e.printStackTrace();
		}
		return builder.toString();
	}
	
	/**calculates the distance between two GeoPoints in km
	 * 
	 * @param StartP
	 * @param EndP
	 * @return double
	 */
	private static double distance (GeoPoint StartP, GeoPoint EndP) {
    	Double lat1 = StartP.getLatitudeE6()/1E6;
    	Double lat2 = EndP.getLatitudeE6()/1E6;
    	Double lon1 = StartP.getLongitudeE6()/1E6;
    	Double lon2 = EndP.getLongitudeE6()/1E6;
    	Double dLat = Math.toRadians(lat2-lat1);
    	double dLon = Math.toRadians(lon2-lon1);
    	double a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(Math.toRadians(lat1)) *
    			Math.cos(Math.toRadians(lat2)) * Math.sin(dLon/2) * Math.sin(dLon/2);
    	double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    	return Radius * c;
    }

}
